package org.vacoor.nothing.web.controller;

import org.springframework.beans.BeanUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.vacoor.nothing.common.validation.Groups;
import org.vacoor.nothing.web.domain.Filters;
import org.vacoor.nothing.web.domain.Page;
import org.vacoor.nothing.web.domain.Pageable;
import org.vacoor.nothing.web.entity.Idable;
import org.vacoor.nothing.web.service.CrudService;

import java.io.Serializable;
import java.util.Map;


/**
 */
public abstract class NController<E extends Idable<ID>, ID extends Serializable> extends ConventionController<E, ID> {
    //    @Autowired
    protected CrudService<E, ID> crudService;

    /**
     * 分页过滤查询
     *
     * @param filters  过滤条件
     * @param pageable 分页排序
     * @return 分页结果
     */
    @ResponseBody
    @RequestMapping("list")
    public Page<E> list(Filters filters, Pageable pageable) {
        return crudService.findPage(filters, pageable);
    }

    /**
     * 新增
     *
     * @param e
     * @param binding
     * @param redirectAttrs
     * @return
     */
    // 这里有个坑, BindingResult 必须紧跟在验证参数后, 被验证参数的错误信息会传递给紧跟其后的 BindingResult
    @RequestMapping("save")
    public String save(@Validated(Groups.C.class) E e, BindingResult binding, RedirectAttributes redirectAttrs) {
        if (binding.hasErrors()) {
            /*
            if (binding.hasFieldErrors()) {
                return getViewPath("edit");
            }
            */
            return getViewPath("add");
        }
        crudService.save(e);
        return redirectViewPath("/");
    }

    /**
     * 更新
     *
     * @param e
     * @param binding
     * @param redirectAttrs
     * @return
     */
    @RequestMapping("update")
    public String update(@Validated(Groups.U.class)E e, BindingResult binding, RedirectAttributes redirectAttrs) {
        // 正常情况, js验证, 如果绕过, 这里其实可以直接跳到统一的错误页面, 不过暂时还是跳到表单提交页面
        if (binding.hasErrors()) {
            // binding.getGlobalErrors().
            return getViewPath("edit");
        }
        crudService.update(e);
        return redirectViewPath("/");
    }

    @RequestMapping({"add", "edit"})
    public void input(E e, Map<String, Object> model) {
        System.out.println();
    }

    /**
     * 模型预处理
     *
     * @param id 标识符
     */
    @ModelAttribute
    protected E prepareModel(@RequestParam(value = "id", required = false) ID id) {
        if (null != id || (id instanceof String && StringUtils.hasText((String) id))) {
            return crudService.find(id);
        }
        return BeanUtils.instantiate(entityClass);
    }
}
